<?php

namespace App\Models\Meimei\Traits;


use App\Exceptions\LogicException;
use Illuminate\Support\Facades\DB;

Trait SortableTrait
{
    public static $typeTop = 1;
    public static $typeUp = 2;
    public static $typeDown = 3;


    // 上移 $offset 位
    public function up($offset=1)
    {
        /**
         * 取其上$ofsset位sort 为 upSort
         * update sort+1 where sort <= upSort and sort < this->sort
         * set this->sort = upSort
         */
        DB::beginTransaction();
        DB::statement('select * from ' . DB::getConfig('prefix') . $this->getTable() . ' for update');
        $upModel = static::where('sort', '>', $this->sort)
            ->orderBy('sort')
            ->offset($offset-1)
            ->first();
        if (!$upModel){
            throw new LogicException('该目标上移不了这么多位');
        }
        DB::statement('update ' .  DB::getConfig('prefix') . $this->getTable() . ' set sort=sort-1 where sort > ? and sort <= ?', [$this->sort, $upModel->sort]);
        $this->sort = $upModel->sort;
        $this->save();
        DB::commit();
        return true;

    }

    // 下移
    public function down($offset=1)
    {
        /**
         * 取其下一位，更换之，
         */
        DB::beginTransaction();
        DB::statement('select * from ' .  DB::getConfig('prefix').$this->getTable() . ' for update');
        $downModel = static::where('sort', '<', $this->sort)
            ->orderByDesc('sort')
            ->offset($offset-1)
            ->first();
        if (!$downModel){
            throw new LogicException('该目标下移不了这么多位');
        }
        DB::statement('update ' .  DB::getConfig('prefix') .$this->getTable() . ' set sort=sort+1 where sort < ? and sort >= ?', [$this->sort, $downModel->sort]);
        $this->sort = $downModel->sort;
        $this->save();
        DB::commit();
        return true;
    }

    // 置顶
    public function top()
    {
        /**
         * 取其下一位，更换之，
         */
        DB::beginTransaction();
        DB::statement('select * from ' .  DB::getConfig('prefix'). $this->getTable() . ' for update');
        $maxSort = $this->maxSort();
        DB::statement('update ' . DB::getConfig('prefix')  . $this->table . ' set sort=sort-1 where sort>?', [$this->sort]);
        $this->sort = $maxSort;
        $this->save();
        DB::commit();
        return true;
    }

    public function maxSort()
    {
        $max = static::select('sort')->orderByDesc('sort')->first();
        return $max->sort ?? 0;
    }

}
